package modelo;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.text.ParseException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.TreeMap;
import java.util.TreeSet;

import logica.Atomo;
import logica.CalculoProposicional;
import logica.CalculoProposicional.Operador;
import logica.InterpretadorDeFormula;

public class FileParser 
{
	public static final
	String CABECALHO = "#[log-propos]";
	
	public static 
	ModeloProposicional parse(File file) 
	throws ParseException, Exception
	{
		Scanner scan = new Scanner(file);
		
		if(scan.hasNext()==false || scan.nextLine().equals(CABECALHO)==false)
			throw new ParseException("Cabeçalho invalido", -1);
		
		ModeloProposicional modelo = new ModeloProposicional();
		while(scan.hasNext())
		{
			String linha = scan.nextLine();
			
			if(linha.trim().equals("")) //ignore linhas vazias
				continue;
			
			if(linha.contains(":") && linha.length() > linha.indexOf(':')+1) //se tem campo e tem valor
			{
				String campo = linha.substring(0, linha.indexOf(':')).trim();
				
				if(campo.equals(""))
					continue;
				
				else if(campo.equalsIgnoreCase("atomos"))
				{
					String atomos_txt[] = linha.substring(linha.indexOf(':')+1).trim().split(",");
					modelo.calculo.simbolosProposicionais = new HashSet<Atomo>();
					for(String s : atomos_txt)
						if(s.trim().equals("")==false)
							modelo.calculo.simbolosProposicionais.add(new Atomo(s.trim()));
				}
				else if(campo.equalsIgnoreCase("operadores"))
				{
					String operadores_txt[] = linha.substring(linha.indexOf(':')+1).trim().split(",");
					
					modelo.calculo.conectivosLogicos = new HashMap<Operador, String>();
					for(String operador_entry : operadores_txt)
					{
						if(operador_entry.trim().contains(" ") && operador_entry.trim().length() > operador_entry.trim().indexOf(' ')+1)
						{
							String operador_txt = operador_entry.trim().substring(0, operador_entry.trim().indexOf(' '));
							
							if(operador_txt.trim().equals(""))
								continue;
							
							for(Operador operador : CalculoProposicional.Operador.values())
								if(operador_txt.trim().equals(operador.name()))
								{
									String conectivo_txt = operador_entry.trim().substring(operador_entry.trim().indexOf(' ')+1).trim();
									modelo.calculo.conectivosLogicos.put(operador, conectivo_txt);
									break;
								}
						}
					}
				}
				
				else if(campo.equalsIgnoreCase("valoracao") || campo.equalsIgnoreCase("valoracão") || campo.equalsIgnoreCase("valoraçao") || campo.equalsIgnoreCase("valoração") )
				{
					String valoracao_txt[] = linha.substring(linha.indexOf(':')+1).trim().split(",");
					modelo.valoracao = new HashMap<Atomo, Boolean>();
					for(String valoracao_entry : valoracao_txt)
					{
						if(valoracao_entry.trim().contains("=") && valoracao_entry.trim().length() > valoracao_entry.trim().indexOf('=')+1)
						{
							String atomo_txt = valoracao_entry.trim().substring(0, valoracao_entry.trim().indexOf('='));
							
							if(atomo_txt.trim().equals(""))
								continue;
							
							boolean valor = Boolean.parseBoolean(valoracao_entry.trim().substring(valoracao_entry.trim().indexOf('=')+1).trim());
							modelo.valoracao.put(new Atomo(atomo_txt), valor);
						}
					}
				}
				else if(campo.equalsIgnoreCase("formula") || campo.equalsIgnoreCase("fórmula"))
				{
					String formula_txt = linha.substring(linha.indexOf(':')+1).trim();
					System.out.println(formula_txt);
					modelo.formula = new InterpretadorDeFormula(modelo.calculo).interpretar(formula_txt);
				}
			}
		}
		
		if(modelo.formula == null || modelo.valoracao == null || modelo.calculo.conectivosLogicos == null || modelo.calculo.simbolosProposicionais == null)
			throw new ParseException("Definição incompleta do arquivo!", -1);
		
		return modelo;
	}
	
	public static
	void save(ModeloProposicional modelo, File file) 
	throws IOException
	{
		StringBuilder text = new StringBuilder();
		
		text.append(CABECALHO+'\n'); //cabeçalho
		
		text.append("atomos :"); //colocar os atomos
		for(Atomo a : new TreeSet<Atomo>(modelo.calculo.simbolosProposicionais))
			text.append(' '+a.toString()+',');
		text.deleteCharAt(text.length()-1); //retira a ultima virgula
		text.append('\n'); //pula linha
		
		text.append("operadores :");
		for(Operador op : modelo.calculo.conectivosLogicos.keySet())
			text.append(' '+op.name() + ' ' + modelo.calculo.conectivosLogicos.get(op)+',');
		text.deleteCharAt(text.length()-1); //retira a ultima virgula
		text.append('\n'); //pula linha
		
		text.append("formula : "+modelo.formula.toString(true)+'\n');
		
		text.append("valoracao :");
		for(Entry<Atomo, Boolean> valor : new TreeMap<Atomo, Boolean>(modelo.valoracao).entrySet())
			text.append(' '+valor.getKey().toString() + "=" + valor.getValue()+',');
		text.deleteCharAt(text.length()-1); //retira a ultima virgula
		text.append('\n'); //pula linha
		
		Writer w = new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(file)));
		w.write(text.toString());
		w.close();
	}
}
